package com.ft.web.utils;

import cn.hutool.core.bean.DynaBean;
import com.ft.web.viewmodel.TreeSelectModel;
import lombok.experimental.UtilityClass;

import java.util.ArrayList;
import java.util.List;

/**
 * @copyright (C), 2015-2019, XXX有限公司
 * @fileName: ConverterUtils
 * @author: 李阳
 * @date: 2019/6/29 12:52
 * @description: 转换工具类
 * @history: <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
@UtilityClass
public class ConverterUtils {

    /**
     * 将列表转换为树形选项并禁用当前节点及后代的选择
     *
     * @param sourceList      列表数据
     * @param rootId          鉴别根节点的ID值
     * @param parentFieldName 父节点Id关联字段名称
     * @param keyFieldName    键（唯一值）字段名称
     * @param titleFieldName  标题字段名称
     * @param currentId       当前选项的Id，设置了该Id则禁用该Id及后代选择
     * @param <T>             数据源类型
     * @param <TKey>          键类型
     * @return 树形TreeSelectModel
     */
    public static <T, TKey> List<TreeSelectModel> listToTreeDisabled(List<T> sourceList, TKey rootId, String parentFieldName, String keyFieldName, String titleFieldName, TKey currentId) {
        List<TKey> parentIds = new ArrayList<>();
        return listToTreeDisableNode(sourceList, rootId, parentFieldName, keyFieldName, titleFieldName, currentId, parentIds);
    }

    /**
     * 将列表转换为树形选项并选中已选择的节点
     *
     * @param sourceList      列表数据
     * @param rootId          鉴别根节点的ID值
     * @param parentFieldName 父节点Id关联字段名称
     * @param keyFieldName    键（唯一值）字段名称
     * @param titleFieldName  标题字段名称
     * @param selectedNodeIds 当前选中的Id集合
     * @param <T>             数据源类型
     * @param <TKey>          键类型
     * @return 树形TreeSelectModel
     */
    public static <T, TKey> List<TreeSelectModel> listToTreeSelected(List<T> sourceList, TKey rootId, String parentFieldName, String keyFieldName, String titleFieldName, List<TKey> selectedNodeIds) {
        return listToTreeSelectedNode(sourceList, rootId, parentFieldName, keyFieldName, titleFieldName, selectedNodeIds);
    }

    private static <T, TKey> List<TreeSelectModel> listToTreeDisableNode(List<T> sourceList, TKey rootId, String parentFieldName, String keyFieldName, String titleFieldName, TKey currentId, List<TKey> parentIds) {
        List<TreeSelectModel> result = new ArrayList<>();
        List<TreeSelectModel> temp;
        Boolean isCurrentAndAfter;
        for (T source : sourceList) {
            DynaBean bean = DynaBean.create(source);
            if (rootId.equals(bean.get(parentFieldName))) {
                TreeSelectModel childSelect = new TreeSelectModel();
                childSelect.setKey(bean.get(keyFieldName));
                childSelect.setValue(bean.get(keyFieldName));
                childSelect.setTitle(bean.get(titleFieldName));
                childSelect.setParentId(bean.get(parentFieldName));
                if (null != currentId) {
                    isCurrentAndAfter = bean.get(keyFieldName).equals(currentId) || parentIds.contains(bean.get(parentFieldName));
                    childSelect.setDisableCheckbox(isCurrentAndAfter);
                    childSelect.setDisabled(isCurrentAndAfter);
                    childSelect.setSelectable(!isCurrentAndAfter);
                    parentIds.add(bean.get(keyFieldName));
                }
                final Object fullName = bean.safeGet("fullName");
                if (null != fullName) {
                    childSelect.setFullPathName(fullName.toString());
                }
                final Object fullPath = bean.safeGet("fullPath");
                if (null != fullPath) {
                    childSelect.setFullPathKey(fullPath.toString());
                }

                temp = listToTreeDisableNode(sourceList, bean.get(keyFieldName), parentFieldName, keyFieldName, titleFieldName, currentId, parentIds);
                if (temp.size() > 0) {
                    childSelect.setChildren(temp);
                } else {
                    childSelect.setIsLeaf(true);
                }
                result.add(childSelect);
            }
        }
        return result;
    }


    private static <T, TKey> List<TreeSelectModel> listToTreeSelectedNode(List<T> sourceList, TKey rootId, String parentFieldName, String keyFieldName, String titleFieldName, List<TKey> selectedNodeIds) {
        List<TreeSelectModel> result = new ArrayList<>();
        List<TreeSelectModel> temp;
        boolean isSelected;
        for (T source : sourceList) {
            DynaBean bean = DynaBean.create(source);
            if (rootId.equals(bean.get(parentFieldName))) {
                TreeSelectModel childSelect = new TreeSelectModel();
                childSelect.setKey(bean.get(keyFieldName));
                childSelect.setValue(bean.get(keyFieldName));
                childSelect.setTitle(bean.get(titleFieldName));
                childSelect.setParentId(bean.get(parentFieldName));
                if (null != selectedNodeIds && selectedNodeIds.size() > 0) {
                    isSelected = selectedNodeIds.contains(bean.get(keyFieldName));
                    childSelect.setIsSelected(isSelected);
                }
                final Object fullName = bean.safeGet("fullName");
                if (null != fullName) {
                    childSelect.setFullPathName(fullName.toString());
                }
                final Object fullPath = bean.safeGet("fullPath");
                if (null != fullPath) {
                    childSelect.setFullPathKey(fullPath.toString());
                }
                temp = listToTreeSelectedNode(sourceList, bean.get(keyFieldName), parentFieldName, keyFieldName, titleFieldName, selectedNodeIds);
                if (temp.size() > 0) {
                    childSelect.setChildren(temp);
                } else {
                    childSelect.setIsLeaf(true);
                }
                result.add(childSelect);
            }
        }
        return result;
    }
}
